import java.net.*;
import java.io.*;
import java.lang.reflect.*;

public class RpcMain
{
	public static void main(String[] args)throws Exception{
		Hell hell = new HellImpl();
		export(hell,28330);
	}
	public static void export(final Object service,int port)throws Exception{
		ServerSocket server = new ServerSocket(port);
		for(;;) {
			try{
				final Socket socket = server.accept();
				new Thread(new Runnable(){
					public void run(){
						try{
						ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
						String methodName = input.readUTF();
						Class<?>[] parameterTypes = (Class<?>[])input.readObject();
						Object[] arguments = (Object[])input.readObject();
						ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
						Method method = service.getClass().getMethod(methodName,parameterTypes);
						Object result = method.invoke(service,arguments);
						output.writeObject(result);
						output.close();
						input.close();
						}catch(Exception e){
							e.printStackTrace();
						}
					}
				}).start();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}

	public static <T> T refer(final Class<T> serviceInterface,final String host,final int port)throws Exception{
		return (T) java.lang.reflect.Proxy.newProxyInstance(serviceInterface.getClassLoader(),new Class<?>[]{serviceInterface},new InvocationHandler(){
			public Object invoke(Object proxy, Method method, Object[] arguments){				
				try{
					final Socket socket = new Socket(host,port);
					ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
					output.writeUTF(method.getName());
					output.writeObject(method.getParameterTypes());
					output.writeObject(arguments);
					ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
					Object result = input.readObject();
					//input.close();
					//output.close();
					return result;
				}catch(Exception e){
					e.printStackTrace();
				}
				return null;
			}			
		});
	}
}


interface Hell
{
	String warp(String msg);
}

class HellImpl implements Hell
{
	public String warp(String msg){
		System.out.println("->>>>>" + msg);
		return "______" + msg;
	}
}